package presenter.split;

import main.InputBean;
import main.InputMode;
import utils.OnLogListener;
import utils.FileBean;
import presenter.flat.DirFlater;
import utils.FileFilter;
import utils.TextUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Spliter {
    private final String path;
    private final int groupSize;
    private final int startIndex;
    private final String preFix;
    private final OnLogListener listener;
    private static final int MAX = 999;
    private static final String SIZE_DEFAULT = "20";
    private final List<String> used = new ArrayList<>();

    public static void split(InputBean info, OnLogListener listener) {
        Runnable next = () -> {
            String sizeStr = info.path2();
            if (TextUtils.isEmpty(sizeStr)) {
                sizeStr = SIZE_DEFAULT;
            }
            int startIndex = 0;
            try {
                String path4 = info.path4();
                if (!TextUtils.isEmpty(path4)) {
                    startIndex = Integer.parseInt(path4);
                }
            } catch (Exception ex) {
                listener.log(ex.getMessage());
            }
            new Spliter(info.path1(), Integer.parseInt(sizeStr), info.path3(), startIndex, listener);
        };
        if (info.mode() == InputMode.ReSplit) {
            InputBean copy = info.copy();
            copy.set(InputMode.FlatDir);
            DirFlater.flat(copy, new OnLogListener() {
                @Override
                public void log(String content) {
                    listener.log(content);
                }

                @Override
                public void taskFinish() {
                    next.run();
                }
            });
        } else {
            next.run();
        }
    }

    private Spliter(String path, int groupSize, String preFix, int startIndex, OnLogListener listener) {
        this.path = path;
        this.groupSize = groupSize;
        this.startIndex = startIndex;
        this.preFix = preFix;
        this.listener = listener;
        try {
            start();
        } catch (Exception ex) {
            log("任务异常:" + ex.getMessage());
        } finally {
            listener.taskFinish();
        }
    }

    private void start() {
        log("开始分析文件夹结构...");
        List<FileBean> items = FileFilter.filter(true, path, name -> true);
        int size = items.size();
        int lines = size / groupSize + (size % groupSize == 0 ? 0 : 1);
        log(String.format("文件夹分析完毕，共%d个文件，马上按照%d个文件一组进行分割，可分为%d组, 起始num = %d", size, groupSize, lines, startIndex));
        split(items, lines);
        log("文件夹分割完毕！！！");
    }

    private void split(List<FileBean> items, int lines) {
        for (int i = 0; i < lines; i++) {
            String toPath = this.path + toPath();
            int from = i * groupSize;
            int to = Math.min((i + 1) * groupSize, items.size());
            List<FileBean> subList = items.subList(from, to);
            move(toPath, subList);
        }
    }

    private void move(String path, List<FileBean> items) {
        log(String.format("开始移动文件至文件夹：%s", path));
        Iterator<FileBean> iterator = items.iterator();
        while (iterator.hasNext()) {
            FileBean item = iterator.next();
            item.move(path, listener);
        }
    }

    private String toPath() {
        for (int i = 0; i < MAX; i++) {
            String fixPath = fixedPath(i);
            if (!used.contains(fixPath)) {
                File file = new File(String.format("%s%s", path, fixPath));
                if (!file.exists()) {
                    boolean success = file.mkdir();
                    if (success) {
                        used.add(fixPath);
                        log("文件夹创建成功！");
                    } else {
                        log("文件夹创建失败！");
                    }
                    return fixPath;
                }
            }
        }
        return fixedPath(MAX);
    }

    private String fixedPath(int num) {
        return addPreFix(fixNum(num));
    }

    private String fixNum(int i) {
        int index = i + startIndex;
        if (index < 10) {
            return String.format("00%d", index);
        } else if (index < 100) {
            return String.format("0%d", index);
        } else {
            return String.valueOf(index);
        }
    }

    private String addPreFix(String num) {
        if (TextUtils.isEmpty(preFix)) {
            return num;
        } else {
            return String.format("%s-%s", preFix, num);
        }
    }

    private void log(String content) {
        listener.log(content);
    }
}
